﻿using Oracle.DataAccess.Client;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Text;
using WorkFlow.Engine;
using WorkFlow.Engine.NSParser;

namespace WorkFlow.Desinger
{
    public class DesingerDataProcess
    {
        /// <summary>
        ///     将设计器返回的数据解析后保存到数据库
        /// </summary>
        /// <param name="arrs"></param>
        /// <param name="htmls"></param>
        /// <param name="userID"></param>
        /// <returns></returns>
        public bool PraserProcess(string[] arrs, string htmls, int userID)
        {
            /*
                v[0] = "actId";
                v[1] = "actName";
                v[2] = "mainType";
                v[3] = "type";
                v[4] = "out";
                v[5] = "in";
                v[6] = "express";
                v[7] = "users";
                v[8] = "nextAct";
                v[9]= "module"
             */
            const int cols = 10;
            var dt = new DataTable();
            for (int i = 0; i < cols; i++)
            {
                dt.Columns.Add(new DataColumn(arrs[i]));
            }
            dt.Columns.Add("con_id");
            dt.Columns.Add("paraList");//存放参数列表
            int rows = arrs.Length/cols;

            //构建datatable
            ConstructTable(arrs, rows, dt, cols);
            return ValidatePaths(dt) && SaveToDB(htmls, userID, dt);
        }

        /// <summary>
        /// 校验构造的路径的合法性
        /// </summary>
        /// <param name="dt"></param>
        private bool ValidatePaths(DataTable dt)
        {
            int rows = dt == null ? 0 : dt.Rows.Count;
            if (rows == 0) return false;

            var parameterAnalysis = new WfParameterAnalysis();
            for (int r = 0; r < rows; r++)
            {
                if (dt != null)
                    switch (Convert.ToInt32(dt.Rows[r]["type"]))
                    {
                        case WfFieldCode.DbOrSplit:
                            {
                                List<string> paras = parameterAnalysis.GetParams(dt.Rows[r]["express"].ToString());
                                if (paras.Count < 1) return false;
                                    string paralist = paras.Aggregate("", (current, v) => current + (v + ":"));
                                    paralist = paralist.Substring(0, paralist.Length - 1);
                                    dt.Rows[r]["paraList"] = paralist;
                            }
                            break;
                    }
            }// loop rows
            return true;
        }
        /// <summary>
        ///     将数据保存回数据库
        /// </summary>
        /// <param name="htmls"></param>
        /// <param name="userID"></param>
        /// <param name="dt"></param>
        /// <returns></returns>
        private static bool SaveToDB(string htmls, int userID, DataTable dt)
        {
            bool ident;
      //      var parameterAnalysis = new WfParameterAnalysis();
            using (var conn = new OracleConnection(ConfigurationManager.AppSettings["OracleConnectionString"]))
            {
                conn.Open();
                OracleTransaction otrans = conn.BeginTransaction();
                try
                {
                    OracleCommand cmd = conn.CreateCommand();
                    //保存到流程规则库tr_processes
                    cmd.Transaction = otrans;
                    cmd.CommandText =
                        string.Format(@"  insert into tr_processes (f_id,f_name,F_VERSION,f_modify_person,f_start_date,f_end_date,f_type,f_is_activated,f_desinger_content)
  values(seq_r_processes.nextval,'{5}',seq_r_processes.currval,{0},
  to_date('{1}','yyyy-mm-dd hh24:mi:ss'),to_date('{2}','yyyy-mm-dd HH24:MI:SS'),{3},{4},:clob)", userID,
                            DateTime.Now,
                            DateTime.Now, WfFieldCode.DbCommonProc, WfFieldCode.DbFalse, WfFieldCode.DbFalse);
                        //默认设置为未激活;
                    //-----------添加设计器html
                    var op = new OracleParameter("clob", OracleDbType.Clob);
                    cmd.Parameters.Add(op);
                    op.Value = htmls;

                    cmd.ExecuteNonQuery();
                    //取当前process id
                    cmd = conn.CreateCommand();
                    cmd.Transaction = otrans;
                    cmd.CommandText = "select seq_r_processes.currval from dual";
                    object procId = cmd.ExecuteScalar(); //流程ID
                    //-----------保存到活动规则表 tr_activities---------------------------
                    var hact = new Hashtable();
                    int rows = dt.Rows.Count;
                    foreach (DataRow dr in dt.Rows)
                    {
                        //------------------保存活动
                        if (!string.IsNullOrEmpty(dr["mainType"].ToString()) &&
                            !hact.ContainsKey(dr["actId"].ToString().Trim()))
                        {
                            cmd = conn.CreateCommand();
                            cmd.Transaction = otrans;
                            int isNeedOutput = dr["out"].ToString().Trim().IndexOf("N", StringComparison.Ordinal) > -1
                                                   ? WfFieldCode.DbFalse
                                                   : WfFieldCode.DbTrue;
                            cmd.CommandText =
                                string.Format(@"insert into tr_activities (f_id,f_process_id,f_name,f_main_type,f_type,f_need_output,F_DESINGER_ID)
values(SEQ_R_ACTIVITIES.nextval,{0},'{1}',{2},{3},{4},'{5}')", procId, dr["actName"], dr["mainType"], dr["type"],
                                    isNeedOutput, dr["actId"]);
                            //添加活动
                            cmd.ExecuteNonQuery();
                            //取当前活动 id
                            cmd = conn.CreateCommand();
                            cmd.Transaction = otrans;
                            cmd.CommandText = "select SEQ_R_ACTIVITIES.currval from dual";
                            hact.Add(dr["actId"].ToString().Trim(), cmd.ExecuteScalar());
                        } //end if
                    } //end for loop
                    for (int r = 0; r < rows; r++)
                    {
                        DataRow dr = dt.Rows[r];
                        if (!string.IsNullOrEmpty(dr["paraList"].ToString()))
                        {
                                cmd = conn.CreateCommand();
                                cmd.Transaction = otrans;
                                int isNeedIntput = dr["in"].ToString().Trim().IndexOf("N", StringComparison.Ordinal) >
                                                   -1
                                    ? WfFieldCode.DbFalse
                                    : WfFieldCode.DbTrue;
                                cmd.CommandText = string.Format(@"insert into tr_conditions
                                                            (f_id,f_process_id ,f_express,f_para_name,f_desc,f_is_need_input)
                                                values(SEQ_R_CONDITIONS.Nextval,{0},'{1}','{2}','',{3})", procId,
                                    dr["express"], dr["paraList"], isNeedIntput); //添加活动
                                cmd.ExecuteNonQuery();
                                //取当前活动 id
                                cmd = conn.CreateCommand();
                                cmd.Transaction = otrans;
                                cmd.CommandText = "select SEQ_R_CONDITIONS.currval from dual";
                                dr["con_id"] = cmd.ExecuteScalar();
                        }
                        //------------保存到路径规则表 tr_paths---------------------
                        if (!string.IsNullOrEmpty(dr["nextAct"].ToString()))
                        {
                            cmd = conn.CreateCommand();
                            cmd.Transaction = otrans;
                            cmd.CommandText = string.Format(@"insert into tr_paths
(f_id,f_process_id,f_pre_activity,f_after_activity,f_desc,f_condition_id)
values(SEQ_R_PATHS.nextval,{0},{1},{2},'',{3})", procId, hact[dr["actId"].ToString().Trim()],
                                hact[dr["nextAct"].ToString().Trim()] == null
                                    ? -1
                                    : int.Parse(hact[dr["nextAct"].ToString().Trim()].ToString()),
                                string.IsNullOrEmpty(dr["con_id"].ToString())
                                    ? "-1"
                                    : dr["con_id"].ToString()); //添加活动
                            cmd.ExecuteNonQuery();
                        }
                        else
                        {
                            //没有后续活动的活动是结束活动
                            cmd = conn.CreateCommand();
                            cmd.Transaction = otrans;
                            cmd.CommandText = string.Format(@"insert into tr_paths
(f_id,f_process_id,f_pre_activity,f_after_activity,f_desc,f_condition_id)
values(SEQ_R_PATHS.nextval,{0},{1},null,'',-1)", procId, hact[dr["actId"].ToString().Trim()]); //添加活动
                            cmd.ExecuteNonQuery();
                        }
                    }
                    //-----------------保存到活动用户表tr_act_user-------------------------
                    var nodelist = new List<string>();
                    foreach (DataRow dr in dt.Rows)
                    {
                        if (nodelist.Contains(dr["actId"].ToString().Trim())) continue;
                        nodelist.Add(dr["actId"].ToString().Trim());

                        if (string.IsNullOrEmpty(dr["users"].ToString())) continue;
                        //分解用户
                        string[] users = dr["users"].ToString().Split(';');
                        foreach (string v in users)
                        {
                            if (string.IsNullOrEmpty(v)) continue;
                            string[] oru = ParseExpress(v);
                            cmd = conn.CreateCommand();
                            cmd.Transaction = otrans;
                            cmd.CommandText =
                                string.Format(@"insert into tr_act_user (f_id,f_act_id,f_process_id,f_module_id,f_org_id,f_role_id,f_user_id)
values (SEQ_R_ACT_USER.nextval,'{0}','{1}',{2},{3},{4},{5})", hact[dr["actId"].ToString().Trim()], procId,
                                    string.IsNullOrEmpty(dr["module"].ToString())
                                        ? -1
                                        : int.Parse(dr["module"].ToString()), oru[0], oru[1], oru[2]); //添加活动
                            cmd.ExecuteNonQuery();
                        }
                    }
                    otrans.Commit();
                    ident = true;
                }
                catch
                {
                    otrans.Rollback();
                    ident = false;
                }
            }
            return ident;
        }

        /// <summary>
        ///     将数据解析为datatable数据
        /// </summary>
        /// <param name="arrs"></param>
        /// <param name="rows"></param>
        /// <param name="dt"></param>
        /// <param name="cols"></param>
        private static void ConstructTable(string[] arrs, int rows, DataTable dt, int cols)
        {
            for (int i = 1; i < rows; i++)
            {
                DataRow dr = dt.NewRow();
                for (int c = 0; c < cols; c++)
                {
                    dr[c] = arrs[cols*i + c];
                }
                if (!string.IsNullOrEmpty(dr["express"].ToString()))
                {
                    dr["express"] =
                        dr["express"].ToString()
                            .Replace(@"&lt;", "<")
                            .Replace(@"&gt;", ">")
                            .Replace(@"&amp;&amp;", @"&&");
                }

                if (!string.IsNullOrEmpty(dr["users"].ToString()))
                {
                    dr["users"] =
                        dr["users"].ToString()
                            .Replace(@"org_", "")
                            .Replace(@"role_", "")
                            .Replace(@"user_", "");
                }

                #region 将活动,子活动替换为相应的数据库代码

                switch (dr["type"].ToString())
                {
                    case "actCommon":
                        dr["mainType"] = WfFieldCode.DbMainCommonType;
                        dr["type"] = WfFieldCode.DbNone;
                        break;

                    case "actStart":
                        dr["mainType"] = WfFieldCode.DbMainTypeStart;
                        dr["type"] = WfFieldCode.DbNone;
                        break;

                    case "actEnd":
                        dr["mainType"] = WfFieldCode.DbMainTyeFinish;
                        dr["type"] = WfFieldCode.DbNone;
                        break;

                    case "actRollback":
                        dr["mainType"] = WfFieldCode.DBMainTypeRollback;
                        dr["type"] = WfFieldCode.DbNone;
                        break;

                    case "routeOrSplit":
                        dr["mainType"] = WfFieldCode.DbMainRouteType;
                        dr["type"] = WfFieldCode.DbOrSplit;
                        break;

                    case "routeOrJoin":
                        dr["mainType"] = WfFieldCode.DbMainRouteType;
                        dr["type"] = WfFieldCode.DbOrJoin;
                        break;

                    case "routeAndSplit":
                        dr["mainType"] = WfFieldCode.DbMainRouteType;
                        dr["type"] = WfFieldCode.DbAndSplit;
                        break;

                    case "routeAndJoin":
                        dr["mainType"] = WfFieldCode.DbMainRouteType;
                        dr["type"] = WfFieldCode.DbAndJoin;
                        break;

                    case "routeXorSplit":
                        dr["mainType"] = WfFieldCode.DbMainRouteType;
                        dr["type"] = WfFieldCode.DbXorSplit;
                        break;

                    case "routeXorJoin":
                        dr["mainType"] = WfFieldCode.DbMainRouteType;
                        dr["type"] = WfFieldCode.DbXorJoin;
                        break;
                }

                #endregion 将活动,子活动替换为相应的数据库代码

                dt.Rows.Add(dr);
            }
        }

        /// <summary>
        ///     检索用户ID是否在表达式所包含的用户ID中
        /// </summary>
        /// <param name="condtion"></param>
        private static string[] ParseExpress(string condtion)
        {
            /*
             * 解析如下字符串
             * org=1 and role=2 and user!=4
             * org role user三个关键字不能为其他的
             *  org=1
             */
            string[] result = {"0", "0", "0"}; //组织 角色 个人
            if (string.IsNullOrEmpty(condtion)) return result;

            string con = condtion.ToLower().Replace("and", "") + " ";
            char[] chs = con.ToCharArray();
            int count = chs.Length;
            var tempvar = new StringBuilder(); //变量名
            var tempnum = new StringBuilder(); //值
            var tempOpt = new StringBuilder(); //操作符

            for (int i = 0; i < count; i++)
            {
                if (chs[i] >= 'a' && chs[i] <= 'z')
                {
                    //如果是字母
                    tempvar.Append(chs[i]);
                } //end if
                else if (chs[i] <= '9' && chs[i] >= '0')
                {
                    tempnum.Append(chs[i]);
                } // end if
                else if (chs[i] == '=' || chs[i] == '!')
                {
                    tempOpt.Append(chs[i]);
                } //end if
                else if (chs[i] == ' ' && (tempvar.Length > 0 && tempnum.Length > 0 && tempOpt.Length > 0))
                {
                    string key = tempvar.ToString();
                    string opt = tempOpt.ToString();
                    string value = tempnum.ToString();
                    switch (key)
                    {
                        case "org":
                            if (opt.Equals("!=")) result[0] = "-" + value;
                            else result[0] = value;
                            break;

                        case "role":
                            if (opt.Equals("!=")) result[1] = "-" + value;
                            else result[1] = value;
                            break;

                        case "user":
                            if (opt.Equals("!=")) result[2] = "-" + value;
                            else result[2] = value;
                            break;
                    }
                    //-----------清空数据
                    tempvar.Clear();
                    tempnum.Clear();
                    tempOpt.Clear();
                }
            }
            return result;
        }
    }
}